今天接著介紹 Golang 非常強大的 std lib: HTTP
我們直接上 code
package main
import (
"fmt"
"net/http"
)
const port = ":8887"
func main() {
// 定義了路由, 然後處理函式
http.HandleFunc("/hello", Hello)
// 先印個提示訊息
fmt.Println("listening: " + port)
// 監聽 port :8887, 第二個參數可以自訂更詳細的 http 處理函式, 為了簡化先不詳述
http.ListenAndServe(port, nil)
}
func Hello(w http.ResponseWriter, r *http.Request) {
fmt.Fprintln(w, "hello world")
}
可以打開 curl curl localhost:8887/hello
, 做個簡單測試, go 要起個簡單的 http server 就是如此容易
以上小試身手一下, 接著我們實務一點的情況去處理
package main
import (
"encoding/json"
"fmt"
"log"
"net/http"
)
const port = ":8887"
func main() {
// 這邊我們改模擬個 login api
http.HandleFunc("/login", Login)
// 示範怎麼快速把靜態檔案提供出去
http.Handle("/", http.FileServer(http.Dir("public")))
fmt.Println("listening: " + port)
// 這邊做個錯誤捕捉, 有時候自己port被佔到不自知, 有錯誤訊息就比較省時間
err := http.ListenAndServe(port, nil)
if err != nil {
log.Fatal(err)
}
}
// 習慣上會先用個 struct 起來接資料
type userParam struct {
Email string `json:"email"`
Password string `json:"password"`
}
func Login(w http.ResponseWriter, r *http.Request) {
// 由於內建沒有捕捉 method, 我們自己寫
if r.Method != "POST" {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "method not allowed")
return
}
// 這邊開始解析 body資料, 個人是滿喜歡 json decode/encode 這種方式
user := userParam{}
err := json.NewDecoder(r.Body).Decode(&user)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "data error, please try again")
return
}
// 這邊 log 出來看, 資料實際有接收到
fmt.Printf("%+v", user)
// 這邊設定個 headers
w.Header().Set("Content-Type", "application/json")
// 這邊把 w 拿去做 encoder, 資料就會直接出去了
err = json.NewEncoder(w).Encode(user)
if err != nil {
w.WriteHeader(http.StatusBadRequest)
fmt.Fprintf(w, "json encode failed")
return
}
}
第二種我們做了更多示範, 有提供靜態檔案, 有把 post body 資料擷取下來, 並且用 json 回傳, 寫起來舒服因為不用依賴太多東西, 但寫久了還是想偷懶怎辦, 請參考第三種
package main
import (
"fmt"
"log"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/recover"
)
func main() {
app := fiber.New()
// 封裝好的各式中間件, 我們就不需要自己寫了!
app.Use(cors.New()) // cors allow *
app.Use(logger.New()) // logger middleware
app.Use(recover.New()) // recover middleware
// 最大的好處, 直接 serve 出來就是 SPA 了, 方便!
app.Static("/", "public")
app.Get("/hello", Hello)
// 有 method 分類可以用了!
app.Post("/login", Login)
if err := app.Listen(":8887"); err != nil {
log.Fatal(err)
}
}
func Hello(c *fiber.Ctx) error {
return c.SendString("Hello, World 👋!")
}
type userParam struct {
Email string `json:"email"`
Password string `json:"password"`
}
func Login(c *fiber.Ctx) error {
user := &userParam{}
// body parser 也是簡簡單單
err := c.BodyParser(user)
if err != nil {
return c.Status(422).SendString("data error")
}
fmt.Printf("%+v", user)
// 很舒服的就送回去了
return c.JSON(user)
}
推薦進階閱讀:
7天用Go从零实现Web框架Gee教程